home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / SAT 2.4.0 / SAT / Demo ƒ / HeartQuest demo ƒ / scores.p < prev    next >
Encoding:
Text File  |  1997-02-16  |  13.5 KB  |  506 lines  |  [TEXT/PJMM]

  1. {================================================}
  2. {============= Score handling and display ==============}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file manages the display and update of the game scores for HeartQuest.}
  10. { It holds routines for updating high score list, including asking for the name of}
  11. { the player, high score window etc. When making a new game, you will probably}
  12. { need to rewrite this unit a lot. }
  13.  
  14. unit scores;
  15.  
  16. interface
  17.     uses
  18. {$IFC UNDEFINED THINK_PASCAL}
  19.         Types, Quickdraw, ToolUtils, Resources, Dialogs, Events, Controls,{}
  20.         Windows, TextUtils, QuickDrawText, Memory, MixedMode, 
  21. {$ELSEC}
  22.         InterfacesUI, 
  23. {$ENDC}
  24.         TransSkel, SAT, Preferences, GameGlobals, SoundConst, CenterStuff;
  25.  
  26.     var
  27.         score: longint;
  28.  
  29.     procedure DoHighMenu (item: integer);
  30.     procedure InitScores;                    { Loads the high score list and the high score window. }
  31.     procedure ZeroScore;                     { Call this on New Game! }
  32.     procedure AddScore (amount: longint);    { Call this when the player gets points, or with addscore(0) just to redisplay. }
  33.     procedure AddScoreS (amount: longint);    { Call this to redisplay when the animation isn't running. }
  34.     procedure UpdateHigh;                    { Call this on game over! }
  35.  
  36. {Also used by sBonus:}
  37.     function Filter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  38.  
  39. implementation
  40.  
  41. { Highscore record }
  42.     type
  43.         hsRec = record
  44.                 HighScores: array[0..10] of longint;
  45.                 HighPlayer: array[0..10] of str15;
  46.             end;
  47.         hsPtr = ^hsRec;
  48.         hsHnd = ^hsPtr;
  49.  
  50.  
  51.     var
  52.         hs, hsm: hsHnd; { m is for macho mode }
  53.         hsh, hshm: Handle;
  54.  
  55. {Filter function for AskHigh, ok = 1 and cancel = 4}
  56.     function Filter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  57.         var
  58.             theChar: Char;
  59.             kind: integer;
  60.             item: Handle;
  61.             box: Rect;
  62.     begin
  63.         if theEvent.what = updateEvt then
  64.             begin
  65.                 BeginUpdate(theDialog);
  66.                 SetPort(theDialog);
  67.  
  68.                 DrawDialog(theDialog);
  69.  
  70. {Frame ok button}
  71.                 GetDialogItem(theDialog, ok, kind, item, box);
  72.                 InsetRect(box, -4, -4);
  73.                 PenSize(3, 3);
  74.                 FrameRoundRect(box, 15, 15);
  75.  
  76.                 EndUpdate(theDialog);
  77.  
  78.                 Filter := false;
  79.                 Exit(Filter);
  80.             end;
  81.         if theEvent.what = keyDown then
  82.             begin
  83.                 theChar := Char(BitAnd(theEvent.message, charCodeMask));
  84. {if BitAnd(theEvent.modifiers, cmdkey) <> 0 then}
  85. {if theChar = '.' then}
  86.                 if ((BitAnd(theEvent.modifiers, cmdkey) <> 0) and (theChar = '.')) or (theChar = char(27)) then {cmd-. or ESC}
  87.                     begin
  88.                         itemHit := cancel;
  89. {Highlight the cancel button}
  90.                         GetDialogItem(theDialog, cancel, kind, item, box);
  91.                         HiliteControl(ControlHandle(item), 1);
  92.  
  93.                         Filter := true;
  94.                         exit(Filter);
  95.                     end;
  96.                 if (theChar = char(13)) or (theChar = char(3)) then
  97.                     begin
  98.                         itemHit := ok;
  99. {Highlight the OK button}
  100.                         GetDialogItem(theDialog, ok, kind, item, box);
  101.                         HiliteControl(ControlHandle(item), 1);
  102.  
  103.                         Filter := true;
  104.                         exit(Filter);
  105.                     end;
  106.             end;
  107.         Filter := false;
  108.     end; {Filter}
  109.  
  110. {Put a frame around a dialog item. There are better ways to do this, though. The right way}
  111. {is to draw the frame as response to an update event, not just when opening the dialog.}
  112.     procedure FrameDItem (dLog: DialogPtr; iNum: integer);
  113.         var
  114.             iBox: Rect;
  115.             iType: integer;
  116.             iHandle: Handle;
  117.             oldPenState: PenState;
  118.             tmpp: GrafPtr;
  119.     begin
  120.         GetPort(tmpp);
  121.         SetPort(dLog);
  122.         GetPenState(oldPenState);
  123.         GetDialogItem(dLog, iNum, iType, iHandle, iBox);
  124.         InsetRect(iBox, -4, -4);
  125.         PenSize(3, 3);
  126.         FrameRoundRect(iBox, 16, 16);
  127.         SetPenState(oldPenState);
  128.         SetPort(tmpp);
  129.     end;
  130.  
  131. { Ask for players name (at highscore) }
  132.     function AskHigh: str255;
  133.         var
  134.             dialog: DialogPtr;
  135.             oldPort: GrafPtr;
  136.             dRec: DialogRecord;
  137.             itemHit: integer;
  138.             itemHandle: Handle;
  139.             itemType, item: integer;
  140.             itemRect: Rect;
  141.             str: str255;
  142.             levelstr: str255;
  143. {$IFC GENERATINGPOWERPC }
  144.             filterProc: ProcPtr;
  145. {$ENDC}
  146.     begin
  147.         CenterDialog(highDlog);
  148.         GetPort(oldPort);
  149.         dialog := GetNewDialog(highDlog, @dRec, WindowPtr(-1));
  150.         ShowWindow(dialog);
  151.         SelectWindow(dialog);
  152.         SetPort(dialog);
  153.  
  154.         GetDialogItem(dialog, 3, itemType, itemHandle, itemRect);
  155.         SetDialogItemText(itemHandle, features^^.player);
  156.         SelectDialogItemText(dialog, 3, 0, 32767);
  157. {FrameDItem(dialog, 1);}
  158.         itemHit := -1;
  159.  
  160. {$IFC GENERATINGPOWERPC }
  161.         filterProc := NewRoutineDescriptor(@Filter, uppModalFilterProcInfo, GetCurrentISA);
  162. {$ENDC}
  163.  
  164.         while not (itemHit in [ok, cancel]) do
  165. {$IFC GENERATINGPOWERPC }
  166.             ModalDialog(filterProc, itemHit);
  167. {$ELSEC}
  168.         ModalDialog(@Filter, itemHit);
  169. {$ENDC}
  170.         if itemHit = cancel then
  171.             begin
  172.                 AskHigh := '';
  173.             end;
  174.         if itemHit = ok then
  175.             begin
  176.                 GetDialogItem(dialog, 3, itemType, itemHandle, itemRect);
  177.                 GetDialogItemText(itemHandle, str);
  178.                 if length(str) > 15 then
  179.                     str := Copy(str, 1, 15);
  180.                 features^^.player := str;
  181.                 AskHigh := str;
  182.             end;
  183.         CloseDialog(dialog);
  184.         SetPort(oldPort);
  185.     end;
  186.  
  187. {     High Score window handlers }
  188.  
  189.     procedure HighUpdate (resized: boolean);
  190.         var
  191.             s: str255;
  192.             i: integer;
  193.     begin
  194.         EraseRect(theHigh^.portrect);
  195.         TextSize(9);
  196.  
  197.         moveto(10, 20);
  198.         DrawString(MyGetIndString(normalStrID)); {str 9: Normal high score list}
  199.         MoveTo(150, 20);
  200.         DrawString(MyGetIndString(machoStrID)); {str 10: Macho high score list}
  201.         MoveTo(0, 22);
  202.         LineTo(500, 22);
  203.         MoveTo(140, 0);
  204.         LineTo(140, 400);
  205.  
  206.         for i := 1 to 10 do
  207.             begin
  208.                 if not LastMacho and (i = LastHigh) then
  209.                     begin
  210.                         TextFace([bold]);
  211.                         ForeColor(redColor);
  212.                     end;
  213.                 moveto(10, i * 18 + 20);
  214.                 DrawString(hs^^.HighPlayer[i]);
  215.                 moveto(110, i * 18 + 20);
  216.                 NumToString(hs^^.HighScores[i], s);
  217.                 DrawString(s);
  218.  
  219.                 TextFace([]);
  220.                 ForeColor(BlackColor);
  221.                 if LastMacho and (i = LastHigh) then
  222.                     begin
  223.                         TextFace([bold]);
  224.                         ForeColor(redColor);
  225.                     end;
  226.                 moveto(150, i * 18 + 20);
  227.                 DrawString(hsm^^.HighPlayer[i]);
  228.                 moveto(250, i * 18 + 20);
  229.                 NumToString(hsm^^.HighScores[i], s);
  230.                 DrawString(s);
  231.  
  232.                 TextFace([]);
  233.                 ForeColor(BlackColor);
  234.             end;
  235.         TextSize(12);
  236.     end;
  237.  
  238.     procedure HighHalt;
  239.     begin
  240.         CloseWindow(theHigh);
  241.     end;
  242.  
  243.     function InternalAddScore (amount: longint): Rect;
  244.         var
  245.             s: str255;
  246.             r: Rect;
  247.     begin
  248.         score := score + amount;
  249.  
  250.         SetPort(gSAT.backScreen.port);
  251.         SetRect(r, gSAT.offSizeH - 49, 14, gSAT.offSizeH - 2, 155);
  252.         OffsetRect(r, 2, 2);
  253.         PaintRoundRect(r, 10, 10);
  254.         OffsetRect(r, -2, -2);
  255.         EraseRoundRect(r, 10, 10);
  256.         FrameRoundRect(r, 10, 10);
  257.         NumToString(Score, s);
  258.         MoveTo(gSAT.offSizeH - 47, 30);
  259.         DrawString(MyGetIndString(scoreStrID)); {str 11: Score: }
  260.         MoveTo(gSAT.offSizeH - 47, 50);
  261.         DrawString(s);
  262.  
  263.         if not bonusLevelRunning then
  264.             begin
  265.                 NumToString(bonus, s);
  266.                 MoveTo(gSAT.offSizeH - 47, 80);
  267.                 DrawString(MyGetIndString(bonusStrID)); {str 12: Bonus: }
  268.                 MoveTo(gSAT.offSizeH - 47, 100);
  269.                 DrawString(s);
  270.             end;
  271.  
  272.         NumToString(level, s);
  273.         MoveTo(gSAT.offSizeH - 47, 130);
  274.         DrawString(MyGetIndString(levelStrID)); {str 13: Level: }
  275.         MoveTo(gSAT.offSizeH - 47, 150);
  276.         DrawString(s);
  277.  
  278.         r.right := r.right + 2;
  279.         r.bottom := r.bottom + 2;
  280.         InternalAddScore := r;
  281.     end;
  282.  
  283.     procedure AddScore (amount: longint);
  284.         var
  285.             s: str255;
  286.             r: Rect;
  287.             tmpport: grafptr;
  288.     begin
  289.         GetPort(tmpPort);
  290.         r := InternalAddScore(amount);
  291.         SATBackChanged(r); {Let SAT show it on screen}
  292.         SetPort(tmpPort);
  293.     end;
  294.  
  295.     procedure AddScoreS (amount: longint);
  296.         var
  297.             s: str255;
  298.             r: Rect;
  299.             tmpport: grafptr;
  300.     begin
  301.         GetPort(tmpPort);
  302.         r := InternalAddScore(amount);
  303.         CopyBits(gSAT.backScreen.port^.portbits, gSAT.wind.port^.portBits, r, r, srcCopy, nil);
  304.         CopyBits(gSAT.backScreen.port^.portbits, gSAT.offScreen.port^.portBits, r, r, srcCopy, nil);
  305.         SetPort(tmpPort);
  306.     end;
  307.  
  308.     procedure DoHighMenu (item: integer);
  309.         var
  310.             p: procptr;
  311.             i: integer;
  312.     begin
  313.         case item of
  314.             showhs: 
  315.                 begin
  316.                     ShowWindow(theHigh);
  317.                     SelectWindow(theHigh);
  318.                 end;
  319.             clearhs: 
  320.                 begin
  321.                     if SATQuestionStr(MyGetIndString(sureStrID)) then {str 14: Are you sure you want to erase the high scores?}
  322.                         begin
  323.                             for i := 1 to 10 do
  324.                                 begin
  325.                                     hs^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  326.                                     hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15: Nobody}
  327.                                     hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  328.                                     hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  329.                                 end;
  330.                             hs^^.HighScores[0] := 10000;            { Lowscore }
  331.                             hsm^^.HighScores[0] := 10000;            { Lowscore }
  332.                             ChangedResource(handle(hs));
  333.                             ChangedResource(handle(hsm));
  334.                             HideWindow(theHigh);
  335.                         end;
  336.                 end;
  337.             otherwise
  338.                 ;
  339.         end;
  340.     end;
  341.  
  342.     procedure WindKey (theChar: char; theMods: integer);
  343.     begin
  344.     end;
  345.  
  346. { Call this on game over! }
  347.     procedure UpdateHigh;
  348.         var
  349.             num, len: integer;
  350.             name, s: str255;
  351.     begin
  352.         lastMacho := features^^.macho;
  353.  
  354.         if features^^.macho then
  355.             begin
  356.                 if score > hsm^^.HighScores[10] then
  357.                     begin
  358.                         num := 10;
  359.                         name := AskHigh;
  360.                         NumToString(level, s); {used below, to append level number}
  361. {Max 15 characters! We take some extra trouble to append '…' too.}
  362.                         len := length(stringof(' (', s, ')'));
  363.                         if length(name) > 15 - len then
  364.                             name := Concat(Copy(name, 1, 15 - len - 1), '…');
  365.  
  366.                         if name = '' then { alt length(name) = 0 }
  367.                             exit(updatehigh);
  368.                         while (hsm^^.HighScores[num - 1] < score) and (num > 1) do
  369.                             begin
  370.                                 hsm^^.HighScores[num] := hsm^^.HighScores[num - 1];
  371.                                 hsm^^.HighPlayer[num] := hsm^^.HighPlayer[num - 1];
  372.                                 num := num - 1;
  373.                             end;
  374.                         LastHigh := num; {Remember last high for the highscore display}
  375.                         hsm^^.HighScores[num] := score;
  376.                         hsm^^.HighPlayer[num] := stringof(name, ' (', s, ')'); {AskHigh;}
  377.                         ChangedResource(handle(hsm));
  378.                         HideWindow(theHigh);
  379.                         ShowWindow(theHigh);
  380.                         SelectWindow(theHigh);
  381.                     end;
  382.             end{ if macho }
  383.         else if score > hs^^.HighScores[10] then
  384.             begin
  385.                 num := 10;
  386.                 name := AskHigh;
  387.                 if length(name) > 15 then
  388.                     name := Concat(Copy(name, 1, 14), '…');
  389.  
  390.                 if name = '' then { alt length(name) = 0 }
  391.                     exit(updatehigh);
  392.                 while (hs^^.HighScores[num - 1] < score) and (num > 1) do
  393.                     begin
  394.                         hs^^.HighScores[num] := hs^^.HighScores[num - 1];
  395.                         hs^^.HighPlayer[num] := hs^^.HighPlayer[num - 1];
  396.                         num := num - 1;
  397.                     end;
  398.                 LastHigh := num; {Remember last high for the highscore display}
  399.                 hs^^.HighScores[num] := score;
  400.                 hs^^.HighPlayer[num] := name;
  401.                 ChangedResource(handle(hs));
  402.                 HideWindow(theHigh);
  403.                 ShowWindow(theHigh);
  404.                 SelectWindow(theHigh);
  405.             end;
  406.     end;
  407.  
  408.     procedure ZeroScore;
  409.     begin
  410.         score := 0;
  411.         LastHigh := -1;
  412.     end;
  413.  
  414. {This procedure copies a resource from the file applFile to prefFile (global file numbers,}
  415. {from the unit Preferences).}
  416. {OBSOLETE - should be replaced by the better code in Preferences.p!}
  417.     procedure OldCopyResource (resType: OSType; id: integer);
  418.         var
  419.             h, h2: Handle;
  420.             saveFile: integer;
  421.     begin
  422.         saveFile := CurResFile; {Look where we are so we can restore}
  423.         UseResFile(gAppFile);
  424.  
  425.         h := GetResource(resType, id); {Get res from the appl}
  426.         if h <> nil then
  427.             begin
  428.                 UseResFile(gPrefFile);
  429.                 h2 := GetResource(resType, id);
  430.                 if h2 = nil then {It doesn't already exist}
  431.                     begin
  432.                         DetachResource(h); {Detach it so we can move it.}
  433.                         AddResource(h, resType, id, ''); {Put it into the gPrefFile}
  434.                         ReleaseResource(h);
  435.                     end
  436.                 else {The res always exists. Don't copy.}
  437.                     begin
  438.                         ReleaseResource(h);
  439.                         ReleaseResource(h2);
  440.                     end;
  441.             end;
  442.         UseResFile(saveFile); {restore}
  443.     end;
  444.  
  445.     procedure InitScores;
  446.         var
  447.             i: integer;
  448.             ignoreErr: OSErr;
  449.     begin
  450.         if SetPrefFile(kPrefsFileName, kPrefCreator, kPrefType, gAppFile, gPrefFile, false) then {If a pref file was created, copy high scores to it!}
  451.             begin
  452.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 0); {Normal mode high scores}
  453.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 1); {Macho mode high scores}
  454.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Feat', 0); {Settings}
  455.             end
  456.         else
  457.             gPrefFile := gAppFile; {If we have no pref file, let's make sure we UseResFile to something that exists.}
  458.  
  459.         lastHigh := -1; {no "last"}
  460.  
  461.         theHigh := GetNewWindow(theHighRes, nil, WindowPtr(-1));
  462.         SetPort(theHigh);
  463.         dummy := SkelWindow(theHigh, nil, @WindKey, @HighUpdate, nil, nil, @HighHalt, nil, false);
  464.  
  465.         UseResFile(gPrefFile); {set the resfile to the pref file, if any. If none, gPrefFile will be the app itself!}
  466.  
  467.         hs := hsHnd(GetResource('Bäst', 0));
  468.         if hs = nil then {Didn't exist - create it!}
  469.             begin
  470.                 hs := hsHnd(NewHandle(Sizeof(hsRec)));
  471.                 CheckNoMem(Ptr(hs));
  472.                 for i := 1 to 10 do
  473.                     begin
  474.                         hs^^.HighScores[i] := 0;
  475.                         hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  476.                     end;
  477.                 hs^^.HighScores[0] := 10000;            { Lowscore }
  478.                 AddResource(handle(hs), 'Bäst', 0, 'High scores');
  479.             end
  480.         else {Did exist - check the size!}
  481.             if GetHandleSize(Handle(hs)) < sizeof(hsHnd) then
  482.                 SetHandleSize(Handle(hs), sizeof(hsHnd));
  483.  
  484.         hsm := hsHnd(GetResource('Bäst', 1));
  485.         if hsm = nil then {Didn't exist - create it!}
  486.             begin
  487.                 hsm := hsHnd(NewHandle(Sizeof(hsRec)));
  488.                 CheckNoMem(Ptr(hsm));
  489.                 for i := 1 to 10 do
  490.                     begin
  491.                         hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  492.                         hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  493.                     end;
  494.                 hsm^^.HighScores[0] := 10000;            { Lowscore }
  495.                 AddResource(handle(hsm), 'Bäst', 1, 'High scores');
  496.             end
  497.         else {Did exist - check the size!}
  498.             if GetHandleSize(Handle(hsm)) < sizeof(hsHnd) then
  499.                 SetHandleSize(Handle(hsm), sizeof(hsHnd));
  500.  
  501.         UseResFile(gAppFile);
  502.  
  503.         score := 0;
  504.     end;
  505.  
  506. end.